// run: time -p $exec < input
// opt: 3
#include <iostream>
#include <algorithm>
#include <unordered_map>

long long const mo = 1000000007;
int const maxn = 16;
int n, m;

std::unordered_map<int, long long> f[2];
long long ff[maxn + 1][maxn + 1], gg[maxn + 1], g[maxn + 1], z[maxn + 1][maxn + 1];

long long lowbit(long long x) { return x & -x; }
int clz(int x) { return __builtin_clz(x); }
int lg2(int x) { return !x ? -1 : 31 - clz(x); }
int count_bits(int x) { return __builtin_popcount(x); }

int main()
{
	std::ios::sync_with_stdio(false);

	for (int m = 1; m <= maxn; m++) {
		for (int i = 0; i < 2; i++) f[i].clear();
		int p = 0, q = 1; f[p][0] = 1;
		for (int i = 1; i <= m; i++) {

			for (int j = 0; j < m; j++) {
				std::swap(p, q); f[p].clear();
				for (auto t : f[q]) {
					auto d = t.second;
					auto s = t.first;
					// 横放
					if (j && !(s & (1 << j)) && (s & (1 << (j - 1)))) {
						f[p][s ^ (1 << (j - 1))] += d;
						f[p][s ^ (1 << (j - 1))] %= mo;
					}
					// 竖放或不放
					f[p][s ^ (1 << j)] += d;
					f[p][s ^ (1 << j)] %= mo;
				}
			}

			ff[i][m] = f[p][0];
		}
	}

	for (int m = 1; m <= maxn; m++) {
		for (int s = 0; s < (1 << (m - 1)); s++) {
			for (int i = 1; i <= m; i++) {
				gg[i] = 1; int p = -1, ss = s; ss |= 1 << (m - 1);
				while (ss) {
					int t = lowbit(ss);
					ss ^= t;
					t = lg2(t);
					gg[i] *= (i <= t - p) ? ff[i][t - p] : ff[t - p][i];
					gg[i] %= mo;
					p = t;
				}
			}

			for (int i = 1; i <= m; i++) {
				g[i] = gg[i];
				for (int j = 1; j <= i - 1; j++) {
					g[i] -= g[j] * gg[i - j];
					g[i] = (g[i] + mo) % mo;
				}

				if (count_bits(s) & 1) z[i][m] -= g[i];
				else z[i][m] += g[i];
				z[i][m] = (z[i][m] + mo) % mo;
			}
		}
	}

	while (std::cin >> n >> m) {
		if (m < n) std::swap(n, m);
		std::cout << z[n][m] << "\n";
	}
}

